﻿using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using NewRetail.Application.Components.Dashboard;
using NewRetail.Application.Components.WeChat.Model;
using NewRetail.Application.Core;
using NewRetail.Application.Utility.Hubs;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;


namespace NewRetail.Application.Worker
{
    //大屏页面dashboard的数据刷新
    public class DashboardRefreshingWorker : ApplicationService, ITransientDependency
    {
        #region params
        private readonly ILogger _logger;
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly IHubContext<NewRetailHub> _hubContext;
        private readonly RedLockFactoryWrapper _redLockFactoryWrapper;
        private readonly ISignalrDealHelper _signalrDealHelper;
        #endregion

        #region 构造
        public DashboardRefreshingWorker(ILogger<DashboardRefreshingWorker> logger, IHubContext<NewRetailHub> hubContext, 
            RedLockFactoryWrapper redLockFactoryWrapper, IUnitOfWorkManager unitOfWorkManager, ISignalrDealHelper signalrDealHelper)
        {
            _logger = logger;
            _redLockFactoryWrapper = redLockFactoryWrapper;
            _hubContext = hubContext;
            _unitOfWorkManager = unitOfWorkManager;
            _signalrDealHelper = signalrDealHelper;
        }
        #endregion

        #region method
        [UnitOfWork]
        public virtual async Task Execute()
        {
            try
            {
                _logger.LogInformation(DateTime.Now.ToString() + "[DashboardDataRefresh]");
                IList<Task> tasks = new List<Task>();
                Task task = TryRefreshDashboardDataAsync();
                tasks.Add(task);
                await Task.WhenAll(tasks);

            }
            catch (Exception e)
            {
                _logger.LogError(e, e.Message);
                throw;
            }
        }
        #endregion

        #region 刷新数据
        [UnitOfWork]
        private async Task TryRefreshDashboardDataAsync(CancellationToken cancellationToken = default)
        {
            // resource 锁定的对象
            // expiryTime 锁定过期时间，锁区域内的逻辑执行如果超过过期时间，锁将被释放
            // waitTime 等待时间,相同的 resource 如果当前的锁被其他线程占用,最多等待时间
            // retryTime 等待时间内，多久尝试获取一次
            using var distributedLock = await _redLockFactoryWrapper.RedLockFactory.CreateLockAsync(
                resource: $"{nameof(DashboardRefreshingWorker)}",
                expiryTime: TimeSpan.FromMinutes(1),
                waitTime: TimeSpan.FromMinutes(1),
                retryTime: TimeSpan.FromSeconds(3));

            if (distributedLock.IsAcquired)
            {
                //dynamic data = new ExpandoObject();
                //data.xData = new string[] { "111", "222", "333", "424", "525", "626" };
                //data.seriesData = new int[] { 121, 121, 226, 30, 50, 110 };
                //var retMsg = new HeaderResult<dynamic>
                //{
                //    Result = data,
                //    IsSucceed = true
                //};
                ////发送数据给前端
                //await _hubContext.Clients.All.SendAsync("ReceiveDashboardMessage", "dtb", retMsg);

                //基础信息概况
                var basicInfoSummary = await _signalrDealHelper.GetBasicInfoSummary();
                await _hubContext.Clients.All.SendAsync("ReceiveDashboardMessage", "baseInfoSummary", basicInfoSummary);
                //今日销售
                var todaySale = await _signalrDealHelper.GetTodaySale();
                await _hubContext.Clients.All.SendAsync("ReceiveDashboardMessage", "todaySale", todaySale);
                //近7日销售
                var lastSevenDaySale = await _signalrDealHelper.GetLastSevenDaySale();
                await _hubContext.Clients.All.SendAsync("ReceiveDashboardMessage", "lastSevenDaySale", lastSevenDaySale);
                //本年度销售
                var yearSale = await _signalrDealHelper.GetYearSale();
                await _hubContext.Clients.All.SendAsync("ReceiveDashboardMessage", "yearSale", yearSale);
                //今日各门店销售
                var todayStoreSale = await _signalrDealHelper.GetTodayStoreSale();
                await _hubContext.Clients.All.SendAsync("ReceiveDashboardMessage", "todayStoreSale", todayStoreSale);
                //今日支付方式占比数据
                var todayPayWaySale = await _signalrDealHelper.GetPaymentWaySale();
                await _hubContext.Clients.All.SendAsync("ReceiveDashboardMessage", "todayPayWaySale", todayPayWaySale);
                //今日购买渠道占比数据
                var todayBuyChannelSale = await _signalrDealHelper.GetBuyChannelSale();
                await _hubContext.Clients.All.SendAsync("ReceiveDashboardMessage", "todayBuyChannelSale", todayBuyChannelSale);

                _logger.LogInformation("刷新数据成功！");
            }
            else
            {
                _logger.LogInformation("未能拿到锁，存在并发");
            }
        }
        #endregion
    }
}
